#include "widget.h"
#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QString>
#include <QDebug>
#include <QImage>

#include "../OpenGL_GP_Lib/opengl_gp_lib.h"

void printFile(QString filename){
    QFile file(filename);
    if(!file.open(QFile::ReadOnly)){
        file.close();
        return;
    }
    QTextStream stream(&file);
    stream.setCodec("UTF-8");
    while (!stream.atEnd()) {
        QString line = stream.readLine();
        line.append('\\').append('n');
        line.prepend('"');
        line.append('"');
        qDebug()<<line.toStdString().data();
    }
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    glgpGetMaxGLContext();
    glgpSetMaxGLContext(1);
    qDebug()<<glgpInitContext();

//    printFile(":/GLSL/ES/convolve2d.fsh");
//    qDebug()<<"\n------------------\n";
//    printFile(":/GLSL/ES/demo.fsh");

    QFile file(":/GLSL/ES/democompute.fsh");
    if(!file.open(QFile::ReadOnly)){
        file.close();
    }else{
        QTextStream stream(&file);
        stream.setCodec("UTF-8");
        QString codetext = stream.readAll();
        file.close();

        glgpLockGLContext(0);

        std::string stdstr = codetext.toStdString();
        unsigned int progrom = glgpComplieShaderProgram3(nullptr,nullptr,
                                                         stdstr.data()
                                                         );
        qDebug()<<progrom;

        unsigned int tex = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_RGBA8UI,512,512,nullptr);
        qDebug()<<tex;

        glgpBindImageTexture(0,tex);
        glgpInvokeComputeProgram(progrom,16,16,1);
        glgpClientWait(1000000L);
        glgpBindImageTexture(0,0);

        unsigned char * resultdata = new unsigned char[4*512*512];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*512*512);
        glgpGetTexImage2D(tex,resultdata); //GLF_RGBA8UI,512,512,

        QImage img(resultdata,512,512,QImage::Format_RGBA8888);
        img.save("1st.png");
        delete [] resultdata;

        file.close();

        unsigned int texs[4] = {0};

        texs[0] = tex;
        texs[1] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_RG32F,512,512,nullptr);

        glgpTextureCopy(texs[0],texs[1],1.0f/255.0f,0.5f,0);
        glgpClientWait(1000000L);

        float * covertedbuf = new float[4*512*512];
        std::memset(covertedbuf,0,sizeof (float) * 4*512*512);
        glgpGetTexImage2D(texs[1],covertedbuf); //GLF_RG32F,512,512,
        delete [] covertedbuf;
        covertedbuf = nullptr;

        texs[0] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_R32F,512,512,nullptr);
        glgpSplitTexture(texs[1],  texs[0],0,0,0);
        glgpClientWait(1000000L);
        covertedbuf = new float[512*512];
        std::memset(covertedbuf,0,sizeof (float) *512*512);
        glgpGetTexImage2D(texs[0],covertedbuf); //GLF_RG32F,512,512,
        delete [] covertedbuf;
        covertedbuf = nullptr;

        texs[0] = texs[1];
        texs[1] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_R8UI,512,256,nullptr);
//        glgpCvtFloatToUI(texs[0],texs[1],255.0f,0.0f,0b0001);   //512,512,
        glgpTextureCopy(texs[0],texs[1],255.0f,0.0f,0b0001);
        glgpClientWait(1000000L);

        resultdata = new unsigned char[4*512*512];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*512*512);
        glgpGetTexImage2D(texs[1],resultdata); //GLF_R8UI,512,256,
        img = QImage(resultdata,512,256,QImage::Format_Grayscale8);
        img.save("2nd.png");
        delete [] resultdata;
        resultdata = nullptr;

        glgpDeleteGLTexture(texs[1]);
        texs[1] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_R8UI,512,512,nullptr);
        glgpSplitTexture(tex,  0,texs[1],0,0);
        glgpClientWait(1000000L);

        resultdata = new unsigned char[512*512];
        std::memset(resultdata,0,sizeof (unsigned char) * 512*512);
        glgpGetTexImage2D(texs[1],resultdata);
        img = QImage(resultdata,512,512,QImage::Format_Grayscale8);
        img.save("3rd.png");
        delete [] resultdata;
        resultdata = nullptr;

        for (int i = 0; i < 4; ++i) {
            texs[i] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_R8UI,512,512,nullptr);
        }
        glgpSplitTexture(tex,  texs[0],texs[1],texs[2],texs[3]);
        glgpClientWait(1000000L);

        glgpDeleteGLTexture(tex);
        tex = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_RGBA8UI,512,512,nullptr);
        glgpMergeTextures(tex,  texs[3],texs[1],texs[0],texs[3]);
//        glgpTextureThreshold(tex,tex,100,200,GLGP_THRESH_RANGE);
        glgpClientWait(1000000L);

        resultdata = new unsigned char[4*512*512];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*512*512);
        glgpGetTexImage2D(tex,resultdata);
        img = QImage(resultdata,512,512,QImage::Format_RGBA8888);
        img.save("splitmergeUI.png");
        delete [] resultdata;
        resultdata = nullptr;

        for (int i = 0; i < 4; ++i) {
            glgpDeleteGLTexture(texs[i]);
            texs[i] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_R32F,512,512,nullptr);
        }
        unsigned int texf = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_RGBA32F,512,512,nullptr);
        glgpTextureCopy(tex,texf,1.0f,0,0);
        glgpSplitTexture(texf,  texs[0],texs[1],texs[2],texs[3]);
        glgpMergeTextures(texf,  texs[2],texs[0],texs[1],texs[3]);
        glgpTextureThreshold(texf,texf,100,128,GLGP_THRESH_RANGE,0);
        glgpFillTexture(texf,0,0,0,255,0b1110);
        glgpTextureCopy(texf,tex,1.0f,0,0);
        glgpClientWait(1000000L);
        resultdata = new unsigned char[4*512*512];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*512*512);
        glgpGetTexImage2D(tex,resultdata);
        img = QImage(resultdata,512,512,QImage::Format_RGBA8888);
        img.save("splitmergeFloat.png");
        delete [] resultdata;
        resultdata = nullptr;

        for (int i = 0; i < 4; ++i) {
            glgpDeleteGLTexture(texs[i]);
        }
        texs[0] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_RGBA32F,100,100,nullptr);
        texs[1] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_RGBA8UI,100,100,nullptr);
        glgpTextureROI(texf,texs[0],100,100,0);
        glgpCvtFloatToUI(texs[0],texs[1],1,0,0);
        glgpClientWait(1000000L);
        resultdata = new unsigned char[4*100*100];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*100*100);
        glgpGetTexImage2D(texs[1],resultdata);
        img = QImage(resultdata,100,100,QImage::Format_RGBA8888);
        img.save("textureFloatROI.png");

        std::memset(resultdata,0,sizeof (unsigned char) * 4*100*100);
        glgpFillTexture(texs[1],0,0,0,0,0);
        glgpTextureROI(tex,texs[1],100,100,0);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[1],resultdata);
        img = QImage(resultdata,100,100,QImage::Format_RGBA8888);
        img.save("textureUIROI.png");

        glgpSetTexSwizzle(texs[1],"bgra");  //设置纹理通道顺序 交换第一第三通道，第二四通道不变
        glgpTextureCopy(texs[1],texs[1],1,0,0);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[1],resultdata);
        img.save("TexSwizzle.png");

        glgpDeleteGLTexture(texs[0]);
//        glgpDeleteGLTexture(texs[1]);
        delete [] resultdata;
        resultdata = nullptr;

        glgpFillTexture(texs[1],0,255,0,255,0b1010);
        texs[0] = glgpAllocateGLTexture2D(GLGPFromatEnum::GLF_RGBA8UI,200,200,nullptr);
        glgpFillTexture(texs[0],50,0,50,255,0);
        glgpTextureCopySrc(texs[1],texs[0],50,50,0);
        glgpClientWait(1000000L);
        resultdata = new unsigned char[4*200*200];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*200*200);
        glgpGetTexImage2D(texs[0],resultdata);
        img = QImage(resultdata,200,200,QImage::Format_RGBA8888);
        img.save("copyMakeBorder.png");

        glgpTexelMath(texs[0],texs[0],1.5f,0,GLGP_TEXELMATH_POW,0b0001);    //0.8次方
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img.save("texelPower.png");

        glgpTexelMath(texs[0],texs[0],0,0,GLGP_TEXELMATH_LOG2,0b0001);    //求自然对数
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img.save("texelLog2.png");

        glgpTexturesMath(texs[0],texs[0],texs[0],GLGP_TEXTURESMATH_MUL,0);    //求纹理乘积
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img.save("texturesMultiply.png");

//        glgpTexelMath(texs[0],texs[0],1.414f,0,GLGP_TEXELMATH_LINEAR,0b0001);
        glgpTexturesMath(texs[0],texs[0],texs[0],GLGP_TEXTURESMATH_AMPLITUDE,0b0001);    //求纹理乘积
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img.save("texturesAmplitude.png");
        glgpDeleteGLTexture(texs[1]);
        delete [] resultdata;
        resultdata = nullptr;

        texs[1] = glgpAllocateGLTexture2D(GLF_RGBA8UI,400,400,nullptr);
        glgpResizeTexture(texs[0],texs[1],1);
        resultdata = new unsigned char[4*400*400];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*400*400);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[1],resultdata);
        img = QImage(resultdata,400,400,QImage::Format_RGBA8888);
        img.save("resizeTex.png");
        glgpDeleteGLTexture(texs[0]);

        float fp[4][2]={
            {0, 0},
            {400, 0},
            {400, 400},
            {0, 400}
        };
        float fp1[4][2]={
            {10, 10},
            {350, 50},
            {320,  350},
            {60,  300},
        };
        float m[3][3] ={{0}};

        qDebug()<<"-------------------------------";
        qDebug()<<"getPerspectM "<<glgpGetPerspectiveTransform(&fp[0][0],&fp1[0][0],&m[0][0]);
        for (int i = 0; i < 3; ++i) {
            qDebug()<<m[0][i]<<","<<m[1][i]<<","<<m[2][i];
        }
        texs[0] = glgpAllocateGLTexture2D(GLF_RGBA8UI,400,400,nullptr);
        glgpWarpPerspective(texs[1],texs[0],&m[0][0]);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img.save("texPerspective.png");

        qDebug()<<"-------------------------------";

        qDebug()<<"getAffineM "<<glgpGetAffineTransform(&fp[0][0],&fp1[0][0],&m[0][0]);

        for (int i = 0; i < 2; ++i) {
            qDebug()<<m[0][i]<<","<<m[1][i]<<","<<m[2][i];
        }

        glgpWarpAffine(texs[1],texs[1],&m[0][0]);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[1],resultdata);
        img.save("texAffine.png");

        qDebug()<<"-------------------------------";

        delete [] resultdata;
        resultdata = nullptr;

        glgpDeleteGLTexture(texs[1]);
        texs[1] = glgpAllocateGLTexture2D(GLF_RGBA8UI,512,512,nullptr);
        glgpResizeTexture(texs[0],texs[1],0);
        resultdata = new unsigned char[4*512*512];
        std::memset(resultdata,0,sizeof (unsigned char) * 4*512*512);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[1],resultdata);
        img = QImage(resultdata,512,512,QImage::Format_RGBA8888);
        img.save("resizeTex2.png");

        glgpDeleteGLTextures(2,&texs[0]);
        delete [] resultdata;
        resultdata = nullptr;

        /////fft test /////
        file.setFileName(":/GLSL/ES/fftcompute.fsh");
        file.open(QFile::ReadOnly);
        stream.setDevice(&file);
        stream.setCodec("UTF-8");
        codetext = stream.readAll();
        stdstr = codetext.toStdString();
        file.close();

//        unsigned int fftprog =
//                glgpComplieShaderProgram3(nullptr,nullptr,stdstr.data());
//        qDebug()<<glgpGet2DFFTShaderCode();
//        glgpReplace2DFFTProgram(fftprog);

        unsigned int pbos[2] = {0};
        pbos[0] = glgpAllocateGLPixelBufferObj(GLGP_PBO_ToOpenGL,
                                               GLGP_BUF_USAGE_DYNAMIC_DRAW,
                                               1024 * 300 * sizeof(unsigned short)
                                               );

        file.setFileName("1024x300x16bit_ui.data");
        file.open(QFile::ReadOnly);
        resultdata = new unsigned char[file.size()];
        void *pbo_mmptr = glgpMapPBOMemory(pbos[0],GLGP_PBO_ToOpenGL);
        file.read(reinterpret_cast<char*>(resultdata),file.size());
        std::memcpy(pbo_mmptr,resultdata,static_cast<size_t>(file.size()));
        glgpUnmapPBOMemory(pbos[0],GLGP_PBO_ToOpenGL);
        file.close();
//        texs[1] = glgpAllocateGLTexture2D(GLF_R16UI,1024,300,resultdata);
        texs[1] = glgpAllocateGLTexture2D(GLF_R16UI,1024,300,nullptr);
        texs[0] = glgpAllocateGLTexture2D(GLF_R8UI,1024,300,nullptr);
        glgpAsyncCopyPBOtoTex2D(pbos[0],texs[1]);
        glgpTextureCopy(texs[1],texs[0],1.0f/256.0f,0,0B0111);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img = QImage(resultdata,1024,300,QImage::Format_Grayscale8);
        img.save("rawdata-MT_8uc1.png");
        glgpDeleteGLTextures(1,&texs[1]);
//        delete [] resultdata;

        texs[1] = glgpAllocateGLTexture2D(GLF_RG32F,1024,300,nullptr);
        GLGP_FFTPlan2D plan;
        glgpCreateTex2DFFTPlan(texs[0],&plan);


        pbos[1] = glgpAllocateGLPixelBufferObj(GLGP_PBO_FromOpenGL,
                                               GLGP_BUF_USAGE_DYNAMIC_READ,
                                               1024 * 300 * sizeof(unsigned char)
                                               );

        covertedbuf = new float[1024 * 2];
        std::memset(covertedbuf,0,sizeof (float) * 1024 * 2);
        glgpGenFFTWindData(covertedbuf,1024,GLGP_FFTWin_Hanning);
        glgpSetTex2DFFTPlanWinData(plan,GLGP_TexFFTMode_ROW,
                                   covertedbuf,1024);
        delete [] covertedbuf;
        covertedbuf = nullptr;

        glgpExecTex2DFFTPlan(plan,texs[0],texs[1],
                GLGP_TexFFTMode_ROW,GLGP_TexFFTDir_FFT,0);
//        glgpExecTex2DFFTPlan(plan,texs[0],texs[0],
//                GLGP_TexFFTMode_ROW_COL,GLGP_TexFFTDir_IFFT,-1.0f);
        glgpTexelMath(texs[1],texs[1],1.0f,0,GLGP_TEXELMATH_AMPLITUDE,0B0011);
        glgpTexelMath(texs[1],texs[1],1.0f,0,GLGP_TEXELMATH_LOG,0B0011);
        glgpClientWait(1000000L);
        glgpDeleteGLTextures(1,&texs[0]);
        texs[0] = glgpAllocateGLTexture2D(GLF_R8UI,1024,300,nullptr);
        glgpTextureCopy(texs[1],texs[0],30.0f,0.0f,0B0111);
        glgpAsyncCopyTex2DtoPBO(texs[0],pbos[1]);
        glgpClientWait(1000000L);
//        glgpGetTexImage2D(texs[0],resultdata);
//        img = QImage(resultdata,1024,300,QImage::Format_Grayscale8);
        pbo_mmptr = glgpMapPBOMemory(pbos[1],GLGP_PBO_FromOpenGL);
        img = QImage(reinterpret_cast<unsigned char *>(pbo_mmptr),
                     1024,300,QImage::Format_Grayscale8);
        img.save("FFT_test1_win.png");
        glgpUnmapPBOMemory(pbos[1],GLGP_PBO_FromOpenGL);

        glgpDeleteGLBufferObj(pbos[1]);
        pbos[1] = glgpAllocateGLPixelBufferObj(GLGP_PBO_FromOpenGL,
                                               GLGP_BUF_USAGE_DYNAMIC_READ,
                                               300 * 512 * sizeof(unsigned char)
                                               );

        glgpDeleteGLTextures(1,&texs[1]);
        texs[1] = glgpAllocateGLTexture2D(GLF_R8UI,512,300,nullptr);
        glgpTextureROI(texs[0],texs[1],0,0,0B0111);
        glgpDeleteGLTexture(texs[0]);
        texs[0] = glgpAllocateGLTexture2D(GLF_R8UI,300,512,nullptr);
        glgpTexTranspose(texs[1],texs[0]);
        glgpAsyncCopyTex2DtoPBO(texs[0],pbos[1]);   //进行了测试，可以一定程序改善glReadPixels读取延时造成的性能损失
        glgpClientWait(1000000L);
//        glgpGetTexImage2D(texs[0],resultdata);
//        img = QImage(resultdata,300,512,QImage::Format_Grayscale8);
        pbo_mmptr = glgpMapPBOMemory(pbos[1],GLGP_PBO_FromOpenGL);
        img = QImage(reinterpret_cast<unsigned char *>(pbo_mmptr),
                     300,512,QImage::Format_Grayscale8);
        img.save("FFT_test1_transpose.png");
        glgpUnmapPBOMemory(pbos[1],GLGP_PBO_FromOpenGL);

        glgpDeleteGLTexture(texs[1]);
        glgpReleaseTex2DFFTPlan(plan);

        texs[1] = glgpAllocateGLTexture2D(GLF_R32UI,256,1,nullptr);
        glgpTex2DHist1DCalc(texs[0],texs[1],256,0,255);
        glgpClientWait(1000000L);
        qDebug()<<"FFT_test1_transpose.png histogram data :";
        glgpGetTexImage2D(texs[1],resultdata);
        {
            QDebug dbg(QtDebugMsg);
            dbg.nospace();
            for (int i = 0; i < 256; ++i) {
                dbg<<reinterpret_cast<unsigned int*>(resultdata)[i]<<",";
            }
        }
        qDebug()<<"--------------------------------------";

        glgpDeleteGLTexture(texs[1]);

        texs[1] = glgpAllocateGLTexture2D(GLF_R32F,5,5,nullptr);
        glgpFillTex2DGaussianKernel(texs[1],10.0f);
        glgpTex2DConvolve2D(texs[0],texs[0],texs[1],1,0);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img = QImage(resultdata,300,512,QImage::Format_Grayscale8);
        img.save("FFT_test1_gaussblur.png");
        glgpDeleteGLTexture(texs[1]);

        texs[1] = glgpAllocateGLTexture2D(GLF_R8UI,300,512,nullptr);
        glgpTex2DSobelConv(texs[0],texs[1],1,1,0);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[1],resultdata);
        img = QImage(resultdata,300,512,QImage::Format_Grayscale8);
        img.save("FFT_test1_sobel.png");
        glgpDeleteGLTexture(texs[1]);

        texs[1] = glgpAllocateGLTexture2D(GLF_R8UI,300,512,nullptr);
        glgpTex2DCanny(texs[0],texs[1],0,1,1);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[1],resultdata);
        img = QImage(resultdata,300,512,QImage::Format_Grayscale8);
        img.save("FFT_test1_canny.png");
        glgpDeleteGLTexture(texs[1]);

        texs[1] = glgpAllocateGLTexture2D(GLF_RG32F,512,512,nullptr);
        glgpCreateTex2DFFTPlan(texs[0],&plan);
        glgpExecTex2DFFTPlan(plan,texs[0],texs[1],
                GLGP_TexFFTMode_ROW_COL,GLGP_TexFFTDir_FFT,0);
//        glgpExecTex2DFFTPlan(plan,texs[1],texs[1],
//                GLGP_TexFFTMode_COL,GLGP_TexFFTDir_FFT,0);
        glgpDeleteGLTexture(texs[0]);
        texs[0] = glgpAllocateGLTexture2D(GLF_R8UI,512,512,nullptr);
        glgpTexelMath(texs[1],texs[1],1.0f,0,GLGP_TEXELMATH_AMPLITUDE,0B0011);
        glgpTexelMath(texs[1],texs[1],1.0f,0,GLGP_TEXELMATH_LOG,0B0011);
        glgpTextureCopy(texs[1],texs[0],15.0f,0.0f,0B0111);
        glgpClientWait(1000000L);
        glgpGetTexImage2D(texs[0],resultdata);
        img = QImage(resultdata,512,512,QImage::Format_Grayscale8);
        img.save("FFT_test2_2D.png");

        glgpDeleteGLBufferObjects(2,pbos);
        glgpDeleteGLTextures(2,&texs[0]);
        delete [] resultdata;

        ////////////////////////////////////

        glgpUnlockGLContext(0);
    }


//    printFile(":/GLSL/ES/demo.vsh");
//    qDebug()<<"\n //////////////////////////////////////// \n";
//    printFile(":/GLSL/ES/demo.fsh");
//    qDebug()<<"\n //////////////////////////////////////// \n";
//    printFile(":/GLSL/ES/democompute.fsh");

    return 0;

//    Widget w;
//    w.show();
//    return a.exec();
}

